package com.base.cn.platform.os.service.course.cloud;

import com.base.cn.platform.os.common.constants.CacheConstants;
import com.base.cn.platform.os.common.constants.ConfigName;
import com.base.cn.platform.os.common.j2cache.CustomCacheChannel;
import com.base.cn.platform.os.common.j2cache.J2CacheRegion;
import com.base.cn.platform.os.common.utils.CcLiveUtils;
import com.base.cn.platform.os.common.utils.DateUtils;
import com.base.cn.platform.os.common.utils.ObjectUtils;
import com.base.cn.platform.os.common.utils.StringUtils;
import com.base.cn.platform.os.common.utils.http.HttpUtil;
import com.base.cn.platform.os.common.utils.result.ResultUtil;
import com.base.cn.platform.os.common.utils.sms.SmsSendUtils;
import com.base.cn.platform.os.entity.course.cloud.CloudService;
import com.base.cn.platform.os.entity.course.cloud.DemandEntity;
import com.base.cn.platform.os.entity.course.cloud.LiveEntity;
import com.base.cn.platform.os.entity.course.cloud.PlaybackEntity;
import com.base.cn.platform.os.entity.course.cloud.sms.CsySmsEntity;
import com.base.cn.platform.os.entity.course.cloud.sms.CsySmsService;
import com.base.cn.platform.os.entity.manage.config.SysConfig;
import com.base.cn.platform.os.service.manage.config.SysConfigService;
import com.github.pagehelper.PageInfo;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;

/**
 * 96刻相关接口
 *
 * @author sk
 * @since 2018-03-29
 */
@Service
public class CloudServiceBiz {

    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    public Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
    @Autowired
    private SmsSendUtils smsSendUtils;
    @Autowired
    private CustomCacheChannel customCacheChannel;


    /**
     * 关闭直播
     *
     * @param roomId 直播间id
     */
    public Map<String, Object> close(String roomId,int type)throws IOException {
        if (StringUtils.isEmpty(roomId)) {
            return ResultUtil.ERROR("关闭直播失败");
        }
        TreeMap<String,String> vlasProviderMap = sysConfigService.getSysConfigContext(ConfigName.VLASPROVIDER);
        if(vlasProviderMap.get("type").equals("CC")){
            Map<String, String> params =  new HashMap<>();
            params.put("roomid", roomId);
            Map<String, Object> resultMaps = demand("http://api.csslcloud.net/api/room/close",params);
            if(resultMaps.get("result").equals("OK")){
                return ResultUtil.SUCCESS("关闭直播间成功");
            }
        }
        Map<String, String> params = basic(type);
        params.put("room_id", roomId);
        Optional<String> optional = Optional.of(config("close"));
        if (optional.isPresent()) {
            CloudService response = response(optional.get(), params, new TypeToken<CloudService>() {
            }, true);
            if (response.getCode() == 0) {
                return ResultUtil.SUCCESS("关闭直播成功", roomId);
            }
        }

        return ResultUtil.ERROR("关闭直播失败");

    }

    /**
     * 删除录播
     *
     * @param id_varchar 录播播放码
     */
    public Map<String, Object> delete(String id_varchar)throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("customerKey", config("customerKey"));
        params.put("idVarchar", id_varchar);
        Optional<String> optional = Optional.of(config("deleteVideo"));
        if (optional.isPresent()) {
            CloudService response = response(optional.get(), params, new TypeToken<CloudService>() {
            }, true);
            if (response.getCode() == 0) {
                return ResultUtil.SUCCESS("删除录播成功", id_varchar);
            }
        }
        return ResultUtil.ERROR("删除录播失败");
    }

    /**
     * 录播列表数据
     *
     * @param currentPage 当前页
     * @param name        名字
     * @param status      状态
     * @param fileType      类型
     */
    public PageInfo<DemandEntity> demand(Integer currentPage, String name, String status,String fileType)throws IOException {
        PageInfo<DemandEntity> pageInfo =new PageInfo<>();
        Map<String, String> params = new HashMap<>();
        TreeMap<String, String> config = sysConfigService.getSysConfigContext(ConfigName.V96K);
        int pageSize = 20;
        params.put("customerKey", config.get("customerKey"));
        params.put("currentPage", currentPage.toString());
        params.put("pageSize", String.valueOf(pageSize));
        params.put("name", name);
        params.put("status", status);
        params.put("fileType", fileType);
        Optional<String> optional = Optional.of(config("demand"));
        if (optional.isPresent()) {
            CloudService<DemandEntity> response = response(optional.get(), params, new TypeToken<CloudService<DemandEntity>>() {}, true);
            if (response.getCode() == 0) {
                List<DemandEntity> clouds = response.getData();
                clouds.forEach(DemandEntity::setCreateTime);
                clouds.forEach(DemandEntity::setStatus);
                clouds.forEach(DemandEntity::setDuration);
                pageInfo.setList(clouds);
                setPageData(response.getTotal(),pageSize,currentPage,pageInfo);
            }
        }
        return pageInfo;
    }

    /**
     * 设置页面数据
     * @param total 总记录数
     * @param pageSize 每页记录数
     * @param currentPage 当前页
     * @param pageInfo 页面对象
     */
    private void setPageData(int total,int pageSize,int currentPage,PageInfo<?> pageInfo){
        pageInfo.setTotal(total);
        pageInfo.setPageSize(pageSize);
        pageInfo.setPageNum(currentPage);
        int pages = 0;
        if(total> pageSize){
            if(total % pageSize ==0){
                pages = total / pageSize;
            }else{
                pages = total / pageSize + 1;
            }
        }else{
            pages = 1;
        }
        pageInfo.setPages(pages);
        int[] navPageNums = null;
        if(pages>0 && pages<=8){
            navPageNums = new int[pages];
            for (int i=0;i<pages;i++){
                navPageNums[i] = i+1;
            }
        }else {
            navPageNums = new int[8];
            if(currentPage >= pages-3){
                for(int i=0;i<8;i++){
                    navPageNums[i] = pages-7+i;
                }
            }else if(currentPage <= 5){
                for (int i=0;i<8;i++){
                    navPageNums[i] = i+1;
                }
            }else {
                for (int i=0;i<8;i++){
                    navPageNums[i] = currentPage-4+i;
                }
            }
        }
        pageInfo.setNavigatepageNums(navPageNums);
        if(pageInfo.getPageNum() == 1){
            pageInfo.setIsFirstPage(true);
        }
        if(pageInfo.getPages() == pageInfo.getPageNum()){
            pageInfo.setIsLastPage(true);
        }
    }

    /**
     * 直播列表数据
     *
     * @param currentPage 当前页
     * @param name        名字
     * @param status      状态
     */
    public PageInfo<LiveEntity> live(Integer currentPage, String name, String status,int type)throws IOException {
        PageInfo<LiveEntity> pageInfo =new PageInfo<>();
        Map<String, String> params = basic(type);
        int pageSize = 20;
        params.put("room_name", name);
        params.put("status", status);
        params.put("current_page", currentPage.toString());
        params.put("page_size", String.valueOf(pageSize));
        Optional<String> optional = Optional.of(config("live"));
        if (optional.isPresent()) {
            CloudService<LiveEntity> response = response(optional.get(), params, new TypeToken<CloudService<LiveEntity>>() {
            }, true);
            if (response.getCode() == 0) {
                List<LiveEntity> clouds = response.getData();
                clouds.forEach(LiveEntity::setLiveTime);
                pageInfo.setList(clouds);
                setPageData(response.getTotal(),pageSize,currentPage,pageInfo);
            }
        }
        return pageInfo;
    }



    /**
     * 直播列表数据
     *
     * @param currentPage 当前页
     */
    public PageInfo<Map> ccLive(Integer currentPage)throws IOException {
        PageInfo<Map> pageInfo =new PageInfo<>();
        Map<String, String> params = new HashMap<>();
        params.put("pagenum", "20");
        params.put("pageindex", currentPage.toString());
        Map<String, Object> resultMaps =   demand("http://api.csslcloud.net/api/room/info",params);
        if(resultMaps.get("result").equals("OK")){
            pageInfo.setList((List<Map>) resultMaps.get("rooms"));
            String count = resultMaps.get("count").toString();
            setPageData( (int)Double.parseDouble(count),20,currentPage,pageInfo);
        }

        return pageInfo;
    }

    public List<Map> findCCPlaybackPage(String roomId)throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("roomid",roomId);
        Map<String, Object> resultMaps =   demand("http://api.csslcloud.net/api/v2/record/info",params);
        if(resultMaps.get("result").equals("OK")){
            return (List<Map>) resultMaps.get("records");
        }

        return null;
    }

    /**
     * 客户端进入直播地址
     *
     * @param roomId 直播房间id
     * @param params 用户参数
     */
    public Optional<String> client(String roomId, Map<String, String> params) {
        if (StringUtils.isEmpty(roomId)) {
            return Optional.empty();
        }
        /*Optional<String> url = config("client");
        if (url.isPresent()) {
            params.putAll(basic());
            params.put("room_id", roomId);
            Map<String, String> map = response(url.get(), params, new TypeToken<Map<String, String>>() {
            }, false);
            return Optional.ofNullable(map.get("data"));
        }*/
        return Optional.empty();
    }

    /**
     * 浏览器进入直播
     *
     * @param roomId 直播房间id
     */
    public String browser(String roomId, int role, Object nickname, String code, Object avatar) {
        String browser = this.config("browser");
        return browser + "?userRole=" + role + "&nickname=" + nickname + "&password=" + code + "&roomId=" + roomId
                + "&userAvatar=" + avatar;
    }


    /**
     * 直播回放地址
     *
     * @param roomId 直播房间号
     * @return 回放地址
     */
    public Optional<String> playbackByRoomId(String roomId,int type) throws IOException {
        String playback = this.config("playback");
        Map<String, String> params = this.basic(type);
        params.put("roomId", roomId);
        CloudService<PlaybackEntity> response = this.response(playback, params, new TypeToken<CloudService<PlaybackEntity>>() {
        }, true);
        if (ObjectUtils.isNotEmpty(response) && response.getCode() == 0) {
            Optional<PlaybackEntity> first = response.getFirst();
            if (first.isPresent()) {
                return Optional.ofNullable(first.get().getPlay_url());
            }
        }
        return Optional.empty();
    }

    /**
     * 基本参数
     */
    private Map<String, String> basic(int type) {
        TreeMap<String, String> config = sysConfigService.getSysConfigContext(ConfigName.V96K);
        Map<String, String> params = new HashMap<>();
        StringBuilder identity_id = new StringBuilder();
        StringBuilder identity_pwd = new StringBuilder();
        switch (type){
            case 1:
                identity_id.append(config.get("c_auth_id"));
                identity_pwd.append(config.get("c_auth_key"));
                break;
            case 2:
                identity_id.append(config.get("p_auth_id"));
                identity_pwd.append(config.get("p_auth_key"));
                break;
            case 3:
                identity_id.append(config.get("i_auth_id"));
                identity_pwd.append(config.get("i_auth_key"));
                break;
            default:
                    identity_id.append(config.get("c_auth_id"));
                    identity_pwd.append(config.get("c_auth_key"));
              break;
        }


        params.put("identity_id", identity_id.toString());
        params.put("identity_pwd", identity_pwd.toString());
        return params;
    }

    /**
     * 获取配置项
     *
     * @param key 配置项key
     */
    private String config(String key) {
        TreeMap<String, String> config = sysConfigService.getSysConfigContext(ConfigName.V96K);
        return config.get(key);
    }

    /**
     * 请求响应
     *
     * @param url    请求路径
     * @param params 参数
     * @param token  类型令牌
     * @param list   是否解析data为{@link List}
     * @param <T>    返回类型
     * @return 返回类型
     */
    private <T> T response(String url, Map<String, String> params, TypeToken token, boolean list)throws IOException {
        String response = HttpUtil.doPost(url, params);
        if (list) {
            response = response.replace("\"[]\"", "[]").replace("\"data\":\"\"", "\"data\":[]");
        }
        Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
        return gson.fromJson(response, token.getType());
    }

    /**
     * 客户端进入直播参数 用户部分
     *
     * @param role   0.学员 1.讲师 2.助教
     * @param number 学员id或讲师id
     * @param name   名
     * @param avatar 头像
     * @return 参数
     */
    public Map<String, String> clientParam(String role, Long number, String name, String avatar) {
        Map<String, String> clientParam = new HashMap<>(4);
        clientParam.put("user_role", role);
        clientParam.put("user_number", number.toString());
        clientParam.put("user_name", name);
        clientParam.put("user_avatar", avatar);
        return clientParam;
    }

    /**
     * 浏览器进入直播参数 用户部分
     *
     * @param role   0.学员 1.讲师 2.助教
     * @param name   名
     * @param code   参加码
     * @param avatar 头像
     * @return 参数
     */
    public Map<String, Object> browserPram(int role, Object name, String code, Object avatar) {
        Map<String, Object> clientParam = new HashMap<>();
        clientParam.put("userRole", role);
        clientParam.put("nickname", name);
        clientParam.put("password", code);
        clientParam.put("userAvatar", avatar);
        return clientParam;
    }

    /**
     * 开通268视频服务（96k）
     * @param params
     * @return
     */
    public Map<String, Object> openService(Map<String, String> params) throws IOException {
        //验证手机号
       if(ObjectUtils.isEmpty(params.get("mobileNum"))){
           return  ResultUtil.ERROR("请填写手机号");
        }
      //验证验证码
        if(!params.get("requestType").equals("true")){
           if(ObjectUtils.isEmpty(params.get("mobileCode"))){
                return  ResultUtil.ERROR("请填验证码");
            }
            TreeMap<String,String> configMap = sysConfigService.getSysConfigContext(ConfigName.SMS);
            smsSendUtils.setSmsConfig(configMap);
            boolean isOk = smsSendUtils.validateVideoCloudServiceCode(params.get("mobileNum"),params.get("mobileCode"));
            if(!isOk){
                return ResultUtil.ERROR("手机验证码错误");
            }else{
                params.remove("mobileCode");
            }
        }
        //验证选择的服务是否正确
        if(ObjectUtils.isEmpty(params.get("serviceType"))){
             return ResultUtil.ERROR("请选择要开通的服务");
        }
        //获取配置信息
        SysConfig sysConfig =sysConfigService.getSysConfigByConfigType(ConfigName.V96K);
        TreeMap<String, String> sysConfigContext = sysConfig.getContextTreeMap();
        //身份鉴权码由96k提供
        params.put("channelKey","GD6ro0Y29414x12kSK33");
        //调用96k账号试用申请接口
        Map<String,Object> Map = response("http://admin.96koo.net/common/userApi/registerApply", params, new TypeToken<Map>() {
        }, true);
        //设置申请用户的手机号
        sysConfigContext.put("userMobile",params.get("mobileNum"));
        //设置用户开通服务的类型
        sysConfigContext.put("operation",params.get("operation"));
        //返回信息
        String msg ="获取账号信息失败请联系管理员";
        //返回编码状态
        String code =null;
        //验证返回数据状态
        if(Map.get("code").toString().equals("10010")){
            msg =Map.get("msg").toString();
            code = Map.get("code").toString();
        }else if(Map.get("code").toString().equals("0")){
                Map<String,Object> data = (java.util.Map<String, Object>) Map.get("data");
                if(ObjectUtils.isNotEmpty(data)){
                    //设置96k返回的信息
                    for (Map.Entry<String, Object> m : data.entrySet()) {
                        //设置视频鉴权
                        if(m.getKey().equals("customerkey")){
                            sysConfigContext.put("customerKey", m.getValue().toString());
                        }
                        //设置直播鉴权
                        if(m.getKey().equals("live")){
                            if(ObjectUtils.isNotEmpty(data.get("live"))){
                                List<Map<String,String>> liveList = (List<java.util.Map<String, String>>) m.getValue();
                                liveList.forEach(item -> {
                                    switch (item.get("serviceType")){
                                        case"1":
                                            sysConfigContext.put("c_auth_id", item.get("identityId"));
                                            sysConfigContext.put("c_auth_key", item.get("identityPwd"));
                                            sysConfigContext.put("c_main", item.get("privateDomain"));
                                            sysConfigContext.put("concurrentLive", "true");
                                            break;
                                        case  "2" :
                                            sysConfigContext.put("p_auth_id", item.get("identityId"));
                                            sysConfigContext.put("p_auth_key", item.get("identityPwd"));
                                            sysConfigContext.put("p_main", item.get("privateDomain"));
                                            sysConfigContext.put("personTimeLive", "true");
                                            break;
                                        case "3":
                                            sysConfigContext.put("i_auth_id", item.get("identityId"));
                                            sysConfigContext.put("i_auth_key", item.get("identityPwd"));
                                            sysConfigContext.put("i_main", item.get("privateDomain"));
                                            sysConfigContext.put("interactiveLive", "true");
                                            break;
                                        default:
                                            break;
                                    }
                                });
                            }
                          }
                        }
                    msg ="信息获取成功";
                    code = Map.get("code").toString();
                }
        }
        //保存配置信息
        TreeMap<String,String> treeMap = new TreeMap<>();
        for (Map.Entry<String, String> m : sysConfigContext.entrySet()) {
            treeMap.put(m.getKey(),m.getValue());
            sysConfig.setContext(gson.toJson(treeMap));
        }
        Map<String, Object> stringObjectMap = sysConfigService.saveConfig(sysConfig);
        if(ResultUtil.getSuccess(stringObjectMap)){
            return  ResultUtil.SUCCESS(msg,code);
        }else{
            return  ResultUtil.ERROR(ResultUtil.getMessage(stringObjectMap));
        }

    }


    /**
     * 录播列表数据
     */
    public PageInfo<CsySmsEntity> querySmsStatis(Map<String, Object> params,int type) throws IOException {
        PageInfo<CsySmsEntity> pageInfo =new PageInfo<>();
        if(ObjectUtils.isEmpty(customCacheChannel.get(J2CacheRegion.TWELVE_HOURS_REGION.getKey(),CacheConstants.CSY_SMS).getValue())){
            if(StringUtils.isNotEmpty(getCsyToken())){
               return  pageInfo;
            }
        }
        getSmsStatis(params,pageInfo,type);
        return pageInfo;
    }

    /**
     * 获取创世云短信消费记录
     * @param params
     * @param pageInfo
     * @throws IOException
     */
    private void  getSmsStatis( Map<String, Object> params,PageInfo<CsySmsEntity> pageInfo,int type) throws IOException {

       int size =12;
        HashMap<String, String> map = new HashMap<>();
        if(StringUtils.isEmpty(params.get("start"))&&StringUtils.isEmpty(params.get("end"))){
            params.put("start",DateUtils.format(new Date(),"yyyy-MM-dd"));
            params.put("end",DateUtils.format(new Date(),"yyyy-MM-dd"));
        }
        if (StringUtils.isEmpty(params.get("start"))){
            return;
        }
        if(StringUtils.isEmpty(params.get("end"))){
            params.put("end",DateUtils.format(new Date(),"yyyy-MM-dd"));
        }
        SysConfig sysConfigByConfigType = sysConfigService.getSysConfigByConfigType(ConfigName.SMS);
        String url = "https://sms.chuangcache.com/api/consume/smsStatis";
        map.put("start",params.get("start").toString());
        map.put("end",params.get("end").toString());
        map.put("page",String.valueOf(params.get("page")));
        map.put("size",String.valueOf(size));
        if(type==2){
            TreeMap<String, String> contextTreeMap = sysConfigByConfigType.getContextTreeMap();
            map.put("app_key",contextTreeMap.get("AppKey"));
            url ="https://sms.chuangcache.com/api/consume/smsLog";
        }
        map.put("time",String.valueOf(System.currentTimeMillis()));
        map.put("access_token",customCacheChannel.get(J2CacheRegion.TWELVE_HOURS_REGION.getKey(),CacheConstants.CSY_SMS).getValue().toString());
        CsySmsService<CsySmsEntity> response = responseJson(url, map, new TypeToken<CsySmsService<CsySmsEntity>>() {
                }, true);
                if (response.getStatus() == 1000) {
                    List<CsySmsEntity> clouds = response.getData();
                    pageInfo.setList(clouds);
                    setPageData(Integer.valueOf(response.getPage().get("page_count")),12,Integer.valueOf(map.get("page")),pageInfo);
                }
    }

    /**
     * 获取创世云短信token
     * @return
     * @throws IOException
     */
    private String  getCsyToken() throws IOException {
        StringBuilder tokenUrl = new StringBuilder("https://api.chuangcache.com/OAuth/authorize");
        Map<String, String> tokenParams = new HashMap<>();
        SysConfig sysConfigByConfigType = sysConfigService.getSysConfigByConfigType(ConfigName.SMS);
        TreeMap<String, String> contextTreeMap = sysConfigByConfigType.getContextTreeMap();
        // appid
        tokenParams.put("appid",contextTreeMap.get("appId"));
        tokenParams.put("appsecret",contextTreeMap.get("appSecret"));
        tokenParams.put("grant_type","client_credentials");
        Map<String,Object> map =  responseJson(tokenUrl.toString(), tokenParams, new TypeToken<Map>() {}, false);
        //获取token
        if(ObjectUtils.isNotEmpty(map.get("data"))){
            Map<String,String> datas= (Map<String, String>) map.get("data");
          String   token =datas.get("access_token");
            customCacheChannel.set(J2CacheRegion.TWELVE_HOURS_REGION.getKey(), CacheConstants.CSY_SMS,token);
            return token;
        }
        return  null;
    }

     /* 请求响应
     *
     * @param url    请求路径
     * @param params 参数
     * @param token  类型令牌
     * @param list   是否解析data为{@link List}
     * @param <T>    返回类型
     * @return 返回类型
     */
    private <T> T responseJson(String url, Map<String, String> params, TypeToken token, boolean list)throws IOException {
        String response = HttpUtil.doPostJson(url, params);
        if (list) {
            response = response.replace("\"[]\"", "[]").replace("\"data\":\"\"", "\"data\":[]");
        }
        Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
        return gson.fromJson(response, token.getType());
    }


    public  Map<String, Object>  demand(String url,Map params) throws IOException {
        TreeMap<String,String> vlasProviderMap = sysConfigService.getSysConfigContext(ConfigName.VLASPROVIDER);
        params.put("userid",vlasProviderMap.get("ccAppId"));
        String apiKey = vlasProviderMap.get("liveAppKey");
        long time = System.currentTimeMillis()/1000;
        String hash = CcLiveUtils.createHashedQueryString(params,time,apiKey);
        String result = HttpUtil.doGet(url+"?" + hash);
        return gson.fromJson(result, new TypeToken<Map<String, Object>>() {}.getType());
    }


}
